#include <stdio.h>

float sqrt_approx(float z)
{
	int val_int = *(int *) &z; /* some bits, but as an int */
	/*
	 * To justify the floolowing code, prove that
	 *
	 * ((((val_int / 2 ^m) - b) / 2) + b) * 2^m = ((val_int) - 2^m) / 2) + ((b + 1）/ 2) * 2^m)
	 *
	 * where
	 *
	 * b = exponent bias
	 *  m = number of mantissa bits
	 *
	 */

	val_int -= 1 << 23; /* subtract 2^m */
	val_int >>= 1; /* divide by 2 */
	val_int += 1 << 29; /* add ((b+1)/2) * 2^m. */

	return *(float*)&val_int;	/* interpret again as float. */
}

int main()
{
	printf("%f\n", sqrt_approx(2.0));
}

#if 0
/*
 * intel
 */
0000000000001169 <sqrt_approx>:
    1169:	f3 0f 1e fa          	endbr64 
    116d:	55                   	push   %rbp
    116e:	48 89 e5             	mov    %rsp,%rbp
    1171:	48 83 ec 20          	sub    $0x20,%rsp
    1175:	f3 0f 11 45 ec       	movss  %xmm0,-0x14(%rbp)	// (rbp-0x14)=0x40000000
    117a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    1181:	00 00 
    1183:	48 89 45 f8          	mov    %rax,-0x8(%rbp)		// 0x85d0d000
    1187:	31 c0                	xor    %eax,%eax
    1189:	48 8d 45 ec          	lea    -0x14(%rbp),%rax		// rax=0x7fffffffe12c: 0x40000000
    118d:	8b 00                	mov    (%rax),%eax			// eax=0x40000000
    118f:	89 45 f4             	mov    %eax,-0xc(%rbp)		// 0x40000000
    1192:	8b 45 f4             	mov    -0xc(%rbp),%eax		// 0x40000000
    1195:	2d 00 00 80 00       	sub    $0x800000,%eax		// 0x3f800000=1.0
    119a:	89 45 f4             	mov    %eax,-0xc(%rbp)		// 0x3f800000
    119d:	8b 45 f4             	mov    -0xc(%rbp),%eax		// 0x3f800000
    11a0:	d1 f8                	sar    %eax					// 0x1fc00000		算术右移
    11a2:	89 45 f4             	mov    %eax,-0xc(%rbp)		// 0x1fc00000
    11a5:	8b 45 f4             	mov    -0xc(%rbp),%eax		// 0x1fc00000
    11a8:	05 00 00 00 20       	add    $0x20000000,%eax		// 0x3fc00000
    11ad:	89 45 f4             	mov    %eax,-0xc(%rbp)		// 0x3fc00000
    11b0:	48 8d 45 f4          	lea    -0xc(%rbp),%rax		// 0x7fffffffe134	rbp-0xc=0x7fffffffe134: 0x3fc00000
    11b4:	f3 0f 10 00          	movss  (%rax),%xmm0			// xmm0=0x3fc00000 ===> 1.5
    11b8:	48 8b 45 f8          	mov    -0x8(%rbp),%rax		// rax=0x5a3e17f185d0d000
    11bc:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax		// rax=0
    11c3:	00 00 
    11c5:	74 05                	je     11cc <sqrt_approx+0x63>
    11c7:	e8 94 fe ff ff       	callq  1060 <__stack_chk_fail@plt>
    11cc:	c9                   	leaveq 
    11cd:	c3                   	retq   

00000000000011ce <main>:
    11ce:	f3 0f 1e fa          	endbr64 
    11d2:	55                   	push   %rbp
    11d3:	48 89 e5             	mov    %rsp,%rbp
    11d6:	f3 0f 10 05 2a 0e 00 	movss  0xe2a(%rip),%xmm0        # 2008 <_IO_stdin_used+0x8>	xmm0=0x40000000=2.0
    11dd:	00 
    11de:	e8 86 ff ff ff       	callq  1169 <sqrt_approx>
    11e3:	f3 0f 5a c0          	cvtss2sd %xmm0,%xmm0		// xmm0=0x3ff8000000000000
    11e7:	48 8d 3d 16 0e 00 00 	lea    0xe16(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    11ee:	b8 01 00 00 00       	mov    $0x1,%eax
    11f3:	e8 78 fe ff ff       	callq  1070 <printf@plt>	// 1.500000
    11f8:	b8 00 00 00 00       	mov    $0x0,%eax
    11fd:	5d                   	pop    %rbp
    11fe:	c3                   	retq   
    11ff:	90                   	nop

/*
 * arm
 */
000000000040055c <sqrt_approx>:
  40055c:	d10083ff 	sub	sp, sp, #0x20
  400560:	bd000fe0 	str	s0, [sp, #12]
  400564:	910033e0 	add	x0, sp, #0xc
  400568:	b9400000 	ldr	w0, [x0]
  40056c:	b9001fe0 	str	w0, [sp, #28]
  400570:	b9401fe0 	ldr	w0, [sp, #28]
  400574:	51600000 	sub	w0, w0, #0x800, lsl #12
  400578:	b9001fe0 	str	w0, [sp, #28]
  40057c:	b9401fe0 	ldr	w0, [sp, #28]
  400580:	13017c00 	asr	w0, w0, #1
  400584:	b9001fe0 	str	w0, [sp, #28]
  400588:	b9401fe1 	ldr	w1, [sp, #28]
  40058c:	52a40000 	mov	w0, #0x20000000            	// #536870912
  400590:	0b000020 	add	w0, w1, w0
  400594:	b9001fe0 	str	w0, [sp, #28]
  400598:	910073e0 	add	x0, sp, #0x1c
  40059c:	bd400000 	ldr	s0, [x0]
  4005a0:	910083ff 	add	sp, sp, #0x20
  4005a4:	d65f03c0 	ret

00000000004005a8 <main>:
  4005a8:	a9bf7bfd 	stp	x29, x30, [sp, #-16]!
  4005ac:	910003fd 	mov	x29, sp
  4005b0:	1e201000 	fmov	s0, #2.000000000000000000e+00
  4005b4:	97ffffea 	bl	40055c <sqrt_approx>
  4005b8:	1e22c000 	fcvt	d0, s0
  4005bc:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  4005c0:	911a2000 	add	x0, x0, #0x688
  4005c4:	97ffffa3 	bl	400450 <printf@plt>
  4005c8:	52800000 	mov	w0, #0x0                   	// #0
  4005cc:	a8c17bfd 	ldp	x29, x30, [sp], #16
  4005d0:	d65f03c0 	ret
  4005d4:	00000000 	.inst	0x00000000 ; undefined


#endif

